
Nombres: Andrés Green Garciare
Fecha: 14 de febrero del 2022.
Expediente : ii713504
Profesor: VILLALOBOS RAMOS, OMAR ANTONIO
Repo: https://github.com/andresgreen-byte/Laboratorio-1--Inversion-de-Capital
La diferencia entre un fondo activamente administrado y pasivamente administrado es que, en el activamente administrado, hay una persona o equipo que está activamente tomando decisiones para comprar y vender ciertas acciones, mientras que, en un fondo pasivamente administrado, el fondo sigue a un índice (como el S&P 500) o sigue una estrategia estandarizada que no depende de las decisiones de un individuo o equipo.
La decisión de invertir en fondos activamente administrados contra fondos pasivamente administrados es una decisión que todo individuo inversionista tiene que tomar. El debate entre cual es mejor se ha ido aclareciendo en las últimas décadas, y en los últimos 10 años el fondo activamente administrado que le gane consistentemente al índice más común – el S&P 500 – es extremadamente raro.
Según un estudio hecho por Morningstar, solamente 47% de los fondos activamente manejados tuvieron rendimientos superiores a sus índices respectivos en el periodo de 2020 a el primer semestre de 2021. Cuando tomas un periodo de 10 años, los resultados son aún peores, con tan solo 25% de los fondos activamente manejados teniendo rendimientos superiores a sus índices respectivos.
Es importante recalcar que el rendimiento no es todo cuando se califica a un fondo de inversión ya sea activa o pasivamente administrado. Una de las medidas más comunes para juzgar el desempeño de un fondo de inversión es el Sharpe Ratio, que en términos simples mide el rendimiento respecto al riesgo que estás tomando al hacer una inversión. La fórmula consiste en calcular el promedio de los rendimientos del periodo, restarle la tasa libre de riesgo, y dividir entre la desviación estándar del activo durante el periodo:
$$ \frac{R_p-R_{rf}}{\sigma_p} $$Esta medida le sirve al inversionista para explicar los rendimientos del fondo y para tener un contexto más profundo sobre las decisiones del administrador o del índice. No es lo mismo tener rendimiento alto invirtiendo en activos altamente riesgosos que tener el mismo rendimiento invirtiendo en un activo menos riesgoso. Este indicador es comúnmente utilizado para comparar distintos fondos y se toma por lo general el que tenga un Sharpe Ratio más alto (que significa que el fondo tuvo mayor rendimiento por cada unidad de riesgo que tomó).
El laboratorio pretende comparar el rendimiento y desempeño de un fondo activamente administrado contra uno pasivamente administrado. Para lograr esto, se van a utilizar tres medidas de desempeño que son: rendmiento promedio mensual, rendimiento acumulado del periodo y el ratio de Sharpe. Se va a comparar el ETF de NAFTRAC, que sigue el índice del IPC, contra una estrategia que invierte en los mismos activos dentro de dicho ETF, pero es activamente administrado por señales de compra y de venta.
Primero se necesitan descargar o verificar que existan las siguentes dependencias y librerías de Python, que también están contenidas en el archivo de "requirements.txt":
certifi==2021.10.8
charset-normalizer==2.0.11
idna==3.3
lxml==4.7.1
multitasking==0.0.10
numpy==1.22.1
pandas==1.4.0
pandas-datareader==0.10.0
plotly==5.5.0
python-dateutil==2.8.2
pytz==2021.3
requests==2.27.1
six==1.16.0
tenacity==8.0.1
urllib3==1.26.8
yfinance==0.1.70
Importamos las librerías que se necesitan en "main.py" para poder presentar los resultados del código.
import functions as funct
import data as dt
import warnings
from datetime import datetime
import plotly.express as px
warnings.filterwarnings("ignore")
Primero fue necesario descargar las ponderaciones iniciales del NAFTRAC de la página de BlackRock que administra los fondos de iShares. Después de descargar los datos y aplicar los filtros y modificaciones necesarias, tenemos un DataFrame que nos queda de la siguente manera:
# Variables definidas para el laboratorio
inversion_inicial = 1000000
comision = 0.00125
rf = 0.0575/12 # Tasa de cetes a 28 días según BANXICO
start = datetime.strptime("2020-01-31", '%Y-%m-%d')
end = datetime.strptime("2022-01-26", '%Y-%m-%d')
dt.ponderaciones.sort_values(by=['Peso (%)'],ascending=False).head(5)
| Ticker | Peso (%) | Date | |
|---|---|---|---|
| 4 | AMXL.MX | 13.70 | 2020-01-31 |
| 12 | FEMSAUBD.MX | 11.85 | 2020-01-31 |
| 18 | GFNORTEO.MX | 10.64 | 2020-01-31 |
| 33 | WALMEX.MX | 10.39 | 2020-01-31 |
| 19 | GMEXICOB.MX | 6.03 | 2020-01-31 |
Después fue necesario descargar los datos históricos de los activos que están dentro de NAFTRAC. Para esto se utilizó la librería de yfinance. Para el laboratorio solo era necesario quedarnos con el precio ajustado final de las fechas requeridas, y el DataFrame resultante de los activos con sus precios históricos nos queda así:
dt.stock_dataYF.head(5)
| AC.MX | ALFAA.MX | ALPEKA.MX | ALSEA.MX | AMXL.MX | ASURB.MX | BBAJIOO.MX | BIMBOA.MX | BOLSAA.MX | CEMEXCPO.MX | ... | LIVEPOLC-1.MX | MEGACPO.MX | MXN.MX | OMAB.MX | ORBIA.MX | PE&OLES.MX | PINFRA.MX | RA.MX | TLEVISACPO.MX | WALMEX.MX | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Date | |||||||||||||||||||||
| 2020-01-31 | 97.059425 | 14.138829 | 17.656099 | 45.825001 | 14.693856 | 355.298859 | 29.346191 | 32.497547 | 39.822372 | 7.595 | ... | 94.164879 | 66.420105 | 0.0 | 127.702377 | 40.628593 | 197.247894 | 191.513794 | 102.208054 | 41.678131 | 53.542747 |
| 2020-02-28 | 97.847710 | 12.524671 | 13.264481 | 39.919998 | 14.530020 | 317.866058 | 28.871275 | 28.541702 | 38.117271 | 6.340 | ... | 86.699867 | 61.928192 | 0.0 | 114.834869 | 35.560684 | 177.357193 | 180.268692 | 103.566154 | 36.578236 | 53.523350 |
| 2020-03-31 | 86.630432 | 6.386885 | 8.414780 | 15.180000 | 13.153787 | 218.531067 | 19.260054 | 33.146442 | 33.221977 | 4.930 | ... | 48.888493 | 60.969666 | 0.0 | 71.217690 | 24.104395 | 157.806320 | 149.362274 | 59.141453 | 27.113379 | 54.056648 |
| 2020-04-30 | 86.255280 | 9.839794 | 11.412233 | 19.870001 | 13.668704 | 236.171265 | 17.868216 | 34.213512 | 40.134056 | 5.070 | ... | 57.330894 | 56.449566 | 0.0 | 77.995682 | 26.275549 | 185.993164 | 157.093552 | 55.904713 | 25.434933 | 56.209217 |
| 2020-05-29 | 91.904655 | 11.715942 | 15.445353 | 18.750000 | 13.865309 | 223.608871 | 19.015541 | 33.813950 | 40.643406 | 5.250 | ... | 53.309719 | 64.749428 | 0.0 | 86.701347 | 30.581245 | 210.771576 | 156.887146 | 58.280216 | 26.090420 | 53.668793 |
5 rows × 34 columns
Ya teniendo las ponderaciones y los precios históricos, simplemente necesitamos calcular cúantas acciones se necesitann comprar para cada activo, tomando en cuenta que no se pueden comprar acciones fraccionales, el costo por transacción de 0.00125, y un monto de inversión inicial de 1,000,000 de pesos. El DataFrame resultante nos queda así:
dt.titulos
| AC.MX | ALFAA.MX | ALPEKA.MX | ALSEA.MX | AMXL.MX | ASURB.MX | BBAJIOO.MX | BIMBOA.MX | BOLSAA.MX | CEMEXCPO.MX | ... | LIVEPOLC-1.MX | MEGACPO.MX | MXN.MX | OMAB.MX | ORBIA.MX | PE&OLES.MX | PINFRA.MX | RA.MX | TLEVISACPO.MX | WALMEX.MX | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Date | |||||||||||||||||||||
| 2020-01-31 | 0.017700 | 0.015100 | 0.002500 | 0.008600 | 0.137000 | 0.027500 | 0.008300 | 0.018700 | 0.007200 | 0.043000 | ... | 0.007400 | 0.007900 | 0.031 | 0.018500 | 0.016700 | 0.009100 | 0.016800 | 0.004400 | 0.039600 | 0.103900 |
| 2020-01-31 00:00:00 | 97.059425 | 14.138829 | 17.656099 | 45.825001 | 14.693856 | 355.298859 | 29.346191 | 32.497547 | 39.822372 | 7.595000 | ... | 94.164879 | 66.420105 | 0.000 | 127.702377 | 40.628593 | 197.247894 | 191.513794 | 102.208054 | 41.678131 | 53.542747 |
| Monto Inicial | 17700.000000 | 15100.000000 | 2500.000000 | 8600.000000 | 137000.000000 | 27500.000000 | 8300.000000 | 18700.000000 | 7200.000000 | 43000.000000 | ... | 7400.000000 | 7900.000000 | 31000.000 | 18500.000000 | 16700.000000 | 9100.000000 | 16800.000000 | 4400.000000 | 39600.000000 | 103900.000000 |
| Títulos | 182.000000 | 1068.000000 | 142.000000 | 188.000000 | 9324.000000 | 77.000000 | 283.000000 | 575.000000 | 181.000000 | 5662.000000 | ... | 79.000000 | 119.000000 | inf | 145.000000 | 411.000000 | 46.000000 | 88.000000 | 43.000000 | 950.000000 | 1941.000000 |
| Monto Comprado | 17664.815414 | 15100.269619 | 2507.166103 | 8615.100143 | 137005.515575 | 27358.012115 | 8304.972168 | 18686.089611 | 7207.849411 | 43002.888812 | ... | 7439.025429 | 7903.992493 | NaN | 18516.844711 | 16698.351906 | 9073.403137 | 16853.213867 | 4394.946304 | 39594.224548 | 103926.472893 |
5 rows × 34 columns
Ya teniendo la cantidad de títulos que debemos de comprar, podemos calcular el valor del portafolio inicial simplemente multiplicando el precio del activo en la fecha inicial por la cantidad de títulos, y después agregandole el efectivo que queda después de comprar las acciones. Esto nos proporciona el capital en inversión para todas las fechas con el DataFrame resultante:
inversion_pasiva = funct.passive_investment(dt.ponderaciones,dt.stock_dataYF,inversion_inicial,comision)
example = inversion_pasiva[["Date","Capital"]]
example.head(5)
| Date | Capital | |
|---|---|---|
| 0 | 2020-01-31 | 998848.527997 |
| 1 | 2020-02-28 | 936898.553552 |
| 2 | 2020-03-31 | 789881.629730 |
| 3 | 2020-04-30 | 835259.227593 |
| 4 | 2020-05-29 | 831221.998454 |
Teniendo ya el capital en inversión para cada fecha podemos calcular los rendimientos de mes con mes y los rendimientos acumulados para que nos quede un DataFrame así:
inversion_pasiva = inversion_pasiva.set_index('Date')
inversion_pasiva.tail(5)
| Capital | Rendimiento | Rend Acumulado | |
|---|---|---|---|
| Date | |||
| 2021-09-30 | 1.216356e+06 | -0.034493 | 0.232156 |
| 2021-10-29 | 1.219704e+06 | 0.002752 | 0.234909 |
| 2021-11-30 | 1.191665e+06 | -0.022988 | 0.211920 |
| 2021-12-31 | 1.275077e+06 | 0.069996 | 0.281917 |
| 2022-01-25 | 1.225056e+06 | -0.039230 | 0.242686 |
Para poder compararnos con el mismo índice que estamos intentando replicar, se descargaron los datos de yfinance del IPC para ver como se compara con nuestro intento de replicarlo:
ipc = funct.stock('^MXX',start,end)
ipc.tail(5)
[*********************100%***********************] 1 of 1 completed
| Adj Close | Rendimiento | Rend Acumulado | |
|---|---|---|---|
| Date | |||
| 2021-09-30 | 51385.550781 | -0.036004 | 0.188389 |
| 2021-10-29 | 51309.839844 | -0.001473 | 0.186915 |
| 2021-11-30 | 49698.718750 | -0.031400 | 0.155516 |
| 2021-12-31 | 53272.441406 | 0.071908 | 0.227423 |
| 2022-01-25 | 51104.390625 | -0.040697 | 0.186726 |
Como se puede observar, nuestro intento tuvo rendimientos diferentes que el IPC. Esto se puede explicar posiblemente porque no se hicieron rebalanceos como se hacen para el IPC, y porque ciertas acciones se tuvieron que quitar y convertir a cash por razones operativas.
También se puede visualizar el capital en inversión de nuestro fondo que intentamos replicar en la gráfica:
fig = px.line(inversion_pasiva,y=inversion_pasiva['Capital'],title='Capital Inversión Pasiva',)
fig.show()
Para poder medir el desempeño, podemos calcular el Sharpe Ratio de nuestro fondo para ver cómo nos fue en comparación del riesgo que tomamos:
medid_pasiva = funct.medidas_des(inversion_pasiva,rf,'Pasiva_NAFTRAC_lab')
medid_pasiva
| Pasiva_NAFTRAC_lab | |
|---|---|
| Medida | |
| Rendimiento Promedio Mensual | 0.009707 |
| Rendimiento Mensual Acumulado | 0.242686 |
| Sharpe Ratio Anualizado | 0.306723 |
Normalmente, un Sharpe Ratio arriba de 1 es considerado decente, y los valores inferiores a esto deberían de hacer que el inversionista cuestione las capacidades de los riesgos que está tomando al invertir en este fondo. Como podemos ver, el Sharpe Ratio para nuestro fondo es de 0.30- que es muy bajo. En la siguiente table se pueden mostrar las medidas de desempeño de VOO, un ETF que replica al índice del S&P 500.
dt.voo
| S&P 500 | |
|---|---|
| Medida | |
| Rendimiento Promedio Mensual | 0.015709 |
| Rendimiento Mensual Acumulado | 0.377013 |
| Sharpe Ratio Anualizado | 0.905401 |
En este caso, invertir en el índice más popular del mundo hubiera sido mejor inversión y hubiera presentado mejores rendimientos ajustados al riesgo. El riesgo que se asume al invertir en México no valió la pena para este periodo de tiempo.
A continuación, se mostrará cómo se compara un ETF activamente administrado muy popular llamado ARKK, que es administrado por Cathie Woods, contra QQQ, que es un etf que busca replicar el índice del Nasdaq-100. Los dos ETFs invierten en acciones principalmente situadas en el sector técnologico, y nos servirá para ejemplificar lo que se intentó demostrar con este laboratio dado a que por temas técnicos el fondo activamente adminstrado del laboratorio no se pudo completar.
dt.qqq
| QQQ | |
|---|---|
| Medida | |
| Rendimiento Promedio Mensual | 0.021701 |
| Rendimiento Mensual Acumulado | 0.520827 |
| Sharpe Ratio Anualizado | 1.123186 |
dt.arkk
| ARKK | |
|---|---|
| Medida | |
| Rendimiento Promedio Mensual | 0.022639 |
| Rendimiento Mensual Acumulado | 0.543337 |
| Sharpe Ratio Anualizado | 0.586673 |
En el tiempo solicitado, el índice de ARKK tuvo mejor rendimiento acumulado, pero su Ratio de Sharpe es casi la mitad del de QQQ. El fee de mantenimiento para ARKK son de 0.75% mientras que el fee de mantenimiento para QQQ es de tan solo 0.20%. Una posible conclusión a la que podría llegar un inversionista sólamente viendo el rendimiento acumulado y el Sharpe Ratio Anualizado de ambos fondos es que ARKK maneja una estrategia de inversión mucho más riesgosa (si consideramos la volatilidad como riesgo) que QQQ, pero solamente obtuvo un rendimiento por encima de menos del 3%. Tomando en cuenta el Sharpe Ratio, los rendimientos muy parecidos, y el rendmiento acumulado, este inversionista invertiría su dinero en QQQ y si tuviera su dinero en ARKK, le estaría preguntando a Cathy Woods que qué está haciendo con su dinero. La historia del fondo de Cathy Woods es una que tristemente se ve repetida entre más tiempo pase, y los administradores de fondos se están quedando sin excusas.